// Copyright [2020] <unknown>
#include <bits/stdc++.h>
using namespace std;
#define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
#define dbg(x...) { cerr << "\033[32;1m" << #x << " -> "; err(x); }
void err() { cerr << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cerr << a << ' '; err(x...); }
#else
#define dbg(...)
#endif

#define sz(x) ((int)x.size())

typedef long long LL;

int t;

const int N = 105, M = 105 * 105;

vector<int> G[M];

int x[M], y[M];
int id[N][N];

const int dx[4] = {-1, -1, 1, 1};
const int dy[4] = {-1, 1, -1, 1};

void addEdge(int u, int v) {
    G[u].push_back(v);
    // G[v].push_back(u);
}

int f[M];

void bfs(int s, int d[], int n, int f[]) {
    memset(d, 0x3f3f3f3f, 4 * (n+1));
    queue<int> Q;
    d[s] = 0;
    f[s] = -1;
    Q.push(s);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for (int v : G[u]) {
            if (d[v] > d[u] + 1) {
                d[v] = d[u] + 1;
                Q.push(v);
            }
        }
    }
}

int n, m;

vector<int> getPath(int t, int f[]) {
    vector<int> ans;
    for (int now=t; now!=-1; now=f[now]) {
        ans.push_back(now);
    }
    reverse(ans.begin(), ans.end());
    return ans;
}

vector<int> tsp(int n, vector<int> G[]) {
    static int dp[1<<22][22];
    static pair<int, int> f[1<<22][22];

    memset(dp, 0x3f3f3f3f, sizeof dp);
    dp[1][1] = 0;
    f[1][1] = make_pair(-1, -1);
    int lim = 1<<n;

    auto update = [](int &a, int b) {
        a = min(a, b);
    };

    for (int mask=0; mask<lim; ++mask) {
        for (int i=1; i<=n; ++i) {
            for (int v : G[i]) {
                if ((mask >> (v-1)) & 1)
                    continue;
                int tmask = mask | 1<<(v-1);
                // update(dp[mask | 1<<(v-1)][v], dp[mask][i] + 1);
                if (dp[mask][i] + 1 < dp[tmask][v]) {
                    dp[tmask][v] = dp[mask][i] + 1;
                    f[tmask][v] = make_pair(mask, i);
                }
            }
        }
    }
    dbg(dp[55][2]);
    dbg(f[63][4].first, f[63][4].second);
    pair<int, int> ans(1e9, -1);
    for (int i=1; i<=n; ++i) {
        if (dp[lim-1][i] < ans.first)
            ans = make_pair(dp[lim-1][i], i);
    }

    vector<int> path;
    // f[1] = -1;
    // dbg("FUCK");
    // dbg(ans.second, ans.first);
    for (int nmask=lim-1, now=ans.second; ~nmask; ) {
        path.push_back(now);
        int tmask = f[nmask][now].first, v = f[nmask][now].second;
        nmask = tmask;
        now = v;
    }
    reverse(path.begin(), path.end());
    return path;
}

int main(int argc, char const *argv[]) {
    // code
    scanf("%d", &n);
    m = n + 1;

    int tot = 0;
    for (int i=1; i<=n; ++i) {
        for (int j=1; j<=m; ++j) {
            id[i][j] = ++tot;
            x[tot] = i;
            y[tot] = j;
        }
    }

    for (int i=1; i<=n; ++i) {
        for (int j=1; j<=m; ++j) {
            int u = id[i][j];
            for (int r=0; r<4; ++r) {
                int tx = i + dx[r], ty = j + dy[r];
                if (tx >= 1 && tx <= n && ty >= 1 && ty <= m) {
                    int v = id[tx][ty];
                    addEdge(u, v);
                }
            }
        }
    }

    for (int i=1; i<=n-1; ++i) {
        // addEdge(id[1][i], id[1][i+1]);
        // addEdge(id[n][i+1], id[n][i]);
        addEdge(id[i][m], id[i+1][m]);
        addEdge(id[i+1][1], id[i][1]);
    }
    for (int i=1; i<=m-1; ++i) {
        addEdge(id[1][i], id[1][i+1]);
        addEdge(id[n][i+1], id[n][i]);
    }
    // static int dist[M];
    // bfs(id[1][1], dist, n, f);
    // auto ans = getPath(id[n][n], f);
    // printf("%d\n", sz(ans));
    // for (int id : ans) {
    //     printf("%d %d\n", x[id], y[id]);
    // }

    // printf("%d\n", tsp(tot, G));
    auto ans = tsp(tot, G);
    printf("%d\n", sz(ans)-1);
    for (int v : ans) {
        printf("%d %d\n", x[v], y[v]);
    }

    return 0;
}
